package com.wpen.unit.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public final class FileUtil {

	public static void mkDir(String dir) throws IOException {
		File file = new File(dir);
		if (file.exists()) {
			return;
		} else if (file.mkdir() == false) {
			throw new IOException("Cannot create the directory = " + dir);
		}
	}

	public static void mkDirs(String dir) throws IOException {
		File file = new File(dir);
		if (file.exists()) {
			return;
		} else if (file.mkdirs() == false) {
			throw new IOException("Cannot create directories = " + dir);
		}
	}

	public static String getFileName(String fullFilePath) {
		if (fullFilePath == null) {
			return "";
		}
		int index1 = fullFilePath.lastIndexOf('/');
		int index2 = fullFilePath.lastIndexOf('\\');
		int index = (index1 > index2) ? index1 : index2;
		if (index == -1) {
			return fullFilePath;
		}
		String fileName = fullFilePath.substring(index + 1);
		return fileName;
	}

	public static String getFilePath(String fullFilePath) {
		if (fullFilePath == null) {
			return null;
		}
		int index1 = fullFilePath.lastIndexOf('/');
		int index2 = fullFilePath.lastIndexOf('\\');
		int index = (index1 > index2) ? index1 : index2;
		if (index == -1) {
			return null;
		}
		String filepath = fullFilePath.substring(0, index);
		return filepath;
	}

	public static void createNewFile(String fileName) throws FileNotFoundException, IOException {
		File file = new File(fileName);
		if (!file.exists()) {
			mkDirs(getFilePath(fileName));
			file.createNewFile();
		}
		if (!file.isFile()) {
			throw new IOException("'" + fileName + "' is not a file.");
		}
		if (!file.canWrite()) {
			throw new IOException("'" + fileName + "' is a read-only file.");
		}
	}

	public static void deleteFile(String filename) throws IOException {
		File file = new File(filename);
		if (file.isDirectory()) {
			throw new IOException("IOException -> BadInputException: not a file.");
		}
		if (!file.exists()) {
			throw new IOException("IOException -> BadInputException: file is not exist.");
		}
		if (!file.delete()) {
			throw new IOException("Cannot delete file. filename = " + filename);
		}
	}

	public static void deleteDir(String dirpath) throws IOException {
		File dir = new File(dirpath);
		if (dir.isFile())
			throw new IOException("IOException -> BadInputException: not a directory.");
		File[] files = dir.listFiles();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				File file = files[i];
				if (file.isFile()) {
					file.delete();
				} else {
					deleteDir(file.getName());
				}
			}
		}
		dir.delete();
	}

	public static void writeFile(String fileName, String content) throws FileNotFoundException, IOException {
		writeFile(fileName, content, "ISO-8859-1", false);
	}

	public static void writeFile(String fileName, String content, boolean append)
			throws FileNotFoundException, IOException {
		writeFile(fileName, content, "ISO-8859-1", append);
	}

	public static void writeFile_GBK(String fileName, String content) throws FileNotFoundException, IOException {
		writeFile(fileName, content, "GBK", false);
	}

	public static void writeFile_GBK(String fileName, String content, boolean append)
			throws FileNotFoundException, IOException {
		writeFile(fileName, content, "GBK", append);
	}

	public static void writeFile_UTF8(String fileName, String content) throws FileNotFoundException, IOException {
		writeFile(fileName, content, "UTF-8", false);
	}

	public static void writeFile_UTF8(String fileName, String content, boolean append)
			throws FileNotFoundException, IOException {
		writeFile(fileName, content, "UTF-8", append);
	}

	public static void writeFile(String fileName, String content, String destEncoding, boolean append)
			throws FileNotFoundException, IOException {
		createNewFile(fileName);
		BufferedWriter out = null;
		FileOutputStream fos = new FileOutputStream(fileName, append);
		out = new BufferedWriter(new OutputStreamWriter(fos, destEncoding));
		out.write(content);
		out.flush();

		try {
			if (out != null)
				out.close();
		} catch (IOException ex) {
		}
	}

	public static byte[] getBytes(InputStream inputStream) throws IOException {
		BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
		byte[] block = new byte[4096];
		while (true) {
			int readLength = bufferedInputStream.read(block);
			if (readLength == -1)
				break;
			byteArrayOutputStream.write(block, 0, readLength);
		}
		byte[] retValue = byteArrayOutputStream.toByteArray();

		try {
			if (inputStream != null)
				inputStream.close();
			if (bufferedInputStream != null)
				bufferedInputStream.close();
			if (byteArrayOutputStream != null)
				byteArrayOutputStream.close();
		} catch (IOException ex) {
		}

		return retValue;
	}

	public static void writeFile(String fileName, InputStream inputStream) throws IOException {
		if (inputStream == null) {
			throw new IllegalArgumentException("Does not accept null input");
		}
		byte[] srcByte = FileUtil.getBytes(inputStream);
		OutputStream outputStream = new FileOutputStream(fileName);
		outputStream.write(srcByte);
		outputStream.flush();

		try {
			if (inputStream != null)
				inputStream.close();
			if (outputStream != null)
				outputStream.close();
		} catch (IOException ex) {
		}
	}

	public static StringBuffer readFileWithLine(String fileName) throws FileNotFoundException, IOException {
		StringBuffer _input = new StringBuffer();
		FileReader _frd = new FileReader(new File(fileName));
		BufferedReader _brd = new BufferedReader(_frd);
		String _rs = _brd.readLine();
		while (_rs != null) {
			_input.append(_rs + "\n");
			_rs = _brd.readLine();
		}
		_frd.close();
		_brd.close();
		return _input;
	}

	public static StringBuffer readFileWithLine(String fileName, String charset)
			throws FileNotFoundException, IOException {
		List<String> lists = readFileByLine(fileName, charset);
		StringBuffer _input = new StringBuffer();
		for (String string : lists) {
			_input.append(string + "\n");
		}
		return _input;
	}

	public static List<String> readFileByLine(String fileName, String charset)
			throws FileNotFoundException, IOException {
		List<String> lists = new ArrayList<>();
		BufferedReader _brd = new BufferedReader(
				new InputStreamReader(new FileInputStream(new File(fileName)), charset));
		String _rs = _brd.readLine();
		while (_rs != null) {
			lists.add(_rs);
			_rs = _brd.readLine();
		}
		try {
			if (_brd != null)
				_brd.close();
		} catch (Exception e) {
		}
		return lists;
	}

	public static StringBuffer readFileWithChar(String fileName, String srcEncoding)
			throws FileNotFoundException, IOException {
		StringBuffer result = new StringBuffer(1024);
		BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), srcEncoding));
		char[] block = new char[1024];
		while (true) {
			int readLength = reader.read(block);
			if (readLength == -1)
				break;
			result.append(block, 0, readLength);
		}
		try {
			if (reader != null)
				reader.close();
		} catch (IOException ex) {
		}
		return result;
	}

	public static void copyFile(String srcFilename, String destFilename) throws IOException {
		copyFile(srcFilename, destFilename, true);
	}

	public static void copyFile(String srcFilename, String destFilename, boolean overwrite) throws IOException {
		File srcFile = new File(srcFilename);
		if (!srcFile.exists())
			throw new FileNotFoundException("Cannot find the source file: " + srcFile.getAbsolutePath());
		if (!srcFile.canRead())
			throw new IOException("Cannot read the source file: " + srcFile.getAbsolutePath());

		File destFile = new File(destFilename);
		if (overwrite == false) {
			if (destFile.exists())
				return;
		} else {
			if (destFile.exists()) {
				if (!destFile.canWrite()) {
					throw new IOException("Cannot write the destination file: " + destFile.getAbsolutePath());
				}
			} else {
				mkDirs(getFilePath(destFile.getAbsolutePath()));
				if (!destFile.createNewFile()) {
					throw new IOException("Cannot write the destination file: " + destFile.getAbsolutePath());
				}
			}
		}

		byte[] block = new byte[1024];
		BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile));
		BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(destFile));
		while (true) {
			int readLength = inputStream.read(block);
			if (readLength == -1)
				break;
			outputStream.write(block, 0, readLength);
		}

		try {
			if (inputStream != null)
				inputStream.close();
			if (outputStream != null)
				outputStream.close();
		} catch (IOException ex) {
		}
		destFile.setLastModified(srcFile.lastModified());

	}

	public static void moveFile(String fullfileName, String fulldestName) throws IOException {
		File file = new File(fullfileName);
		if (getFilePath(fulldestName) == null) {
			throw new IOException("plese use AbsolutePath: " + fulldestName);
		}
		file.renameTo(new File(fulldestName));
	}

	public static long getLastModifiedMillis(String fileName) {
		return new File(fileName).lastModified();
	}

	public static Date getLastModifiedDate(String fileName) {
		return new Date(getLastModifiedMillis(fileName));
	}

	public static String getFileSize(String fileName) throws IOException {
		return getHumanSize(getFileLength(fileName));
	}

	public static long getFileLength(String fileName) throws IOException {
		return getFileLength(new File(fileName));
	}

	public static long getFileLength(File fileName) throws IOException {
		long size = 0;
		if (fileName.isDirectory())
			throw new IOException("BadInputException: not a file.");
		if (fileName.isFile())
			size = fileName.length();
		return size;
	}

	public static String getDirSize(String dir) throws IOException {
		return getHumanSize(getDirLength(dir));
	}

	public static long getDirLength(String dir) throws IOException {
		return getDirLength(new File(dir));
	}

	public static long getDirLength(File dir) throws IOException {
		if (dir.isFile())
			throw new IOException("BadInputException: not a directory.");
		long size = 0;
		File[] files = dir.listFiles();
		if (files != null) {
			for (int i = 0; i < files.length; i++) {
				File file = files[i];
				long length = 0;
				if (file.isFile()) {
					length = file.length();
				} else {
					length = getDirLength(file);
				}
				size += length;
			}
		}
		return size;
	}

	public static String getHumanSize(long size) {
		int sizeToStringLength = String.valueOf(size).length();
		String humanSize = "";
		DecimalFormat formatter = new DecimalFormat("##0.##");
		if (sizeToStringLength > 9) {
			humanSize += formatter.format((double) size / (1024 * 1024 * 1024)) + " GB";
		} else if (sizeToStringLength > 6) {
			humanSize += formatter.format((double) size / (1024 * 1024)) + " MB";
		} else if (sizeToStringLength > 3) {
			humanSize += formatter.format((double) size / 1024) + " KB";
		} else {
			humanSize += String.valueOf(size) + " Bytes";
		}
		return humanSize;
	}

}
